package com.xiaoshuidi.cloud.module.contract.controller.admin.contract;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.pdf.PdfWriter;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.excel.core.util.ExcelUtils;
import com.xiaoshuidi.cloud.framework.operatelog.core.annotations.OperateLog;
import com.xiaoshuidi.cloud.module.bpm.api.task.BpmProcessInstanceApi;
import com.xiaoshuidi.cloud.module.bpm.api.task.dto.BpmTaskRespDTO;
import com.xiaoshuidi.cloud.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import com.xiaoshuidi.cloud.module.contract.controller.admin.bill.vo.rentOrder.RentOrderCountVO;
import com.xiaoshuidi.cloud.module.contract.controller.admin.contract.vo.company.CompanyContractRefundReqVO;
import com.xiaoshuidi.cloud.module.contract.controller.admin.contract.vo.settlement.*;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.contract.SettlementDO;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.contract.SettlementDetailDO;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.contract.SettlementExtDO;
import com.xiaoshuidi.cloud.module.contract.enums.ApiConstants;
import com.xiaoshuidi.cloud.module.contract.enums.contract.ContractSettlementTypeEnum;
import com.xiaoshuidi.cloud.module.contract.service.contract.ContractSettlementService;
import com.xiaoshuidi.cloud.module.contract.util.pdf.PdfUtils;
import com.xiaoshuidi.cloud.module.finance.api.order.dto.PayOrderCreateReqDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.xiaoshuidi.cloud.framework.common.pojo.CommonResult.success;
import static com.xiaoshuidi.cloud.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;


@Tag(name = "合同模块 - 退租清单")
@RestController
@Validated
@RequestMapping(ApiConstants.NAME + "/contract-settlement")
public class ContractSettlementController {

    @Resource
    private ContractSettlementService contractSettlementService;
    @Resource
    private BpmProcessInstanceApi bpmProcessInstanceApi;

    @GetMapping("/get")
    @Operation(summary = "通过合同id获取退租清单")
    public CommonResult<ContractSettlementListReqVO> getSettlement(@RequestParam("id") Long contractId) {
        ContractSettlementListReqVO reqVO = contractSettlementService.getSettlementByContractId(contractId);
        return success(reqVO);
    }

    /**
     * 通过清算单id获取租客合同退租清单列表
     *
     * @param id
     * @return
     */
    @GetMapping("/get-id")
    @Operation(summary = "通过合同id获取退租清单")
    public CommonResult<ContractSettlementListReqVO> getSettlementById(@RequestParam("id") Long id) {
        ContractSettlementListReqVO reqVO = contractSettlementService.getSettlementById(id);
        return success(reqVO);
    }

    /**
     * 获取租客合同退租清单列表
     *
     * @param reqVO
     * @return
     */
    @PostMapping("/get-list-person")
    @Operation(summary = "通过合同id获取租客合同退租清单列表")
    public CommonResult<PageResult<ContractSettlementGetListRespVO>> getSettlementPersonList(@RequestBody ContractSettlementGetListReqVO reqVO) {
        PageResult<ContractSettlementGetListRespVO> list = contractSettlementService.getSettlementList(reqVO);
        return success(list);
    }

    /**
     * 企业批量退租清算列表
     *
     * @param reqVO
     * @return
     */
    @PostMapping("/get-batch-list-person")
    @Operation(summary = "企业批量退租清算列表")
    public CommonResult<PageResult<ContractSettlementGetListRespVO>> getSettlementCompanyBatchList(@RequestBody ContractSettlementGetListReqVO reqVO) {
        PageResult<ContractSettlementGetListRespVO> list =
                contractSettlementService.getSettlementCompanyBatchList(reqVO);
        return success(list);
    }

    /**
     * 导出退租清算单
     */
    @GetMapping("/export-settlement")
    @Operation(summary = "退租清算单 Excel")
//    @PreAuthorize("@ss.hasPermission('contract:export')")
    @OperateLog(type = EXPORT)
    public void exportSettlementExcel(ContractSettlementReqExcelVO req, HttpServletResponse response) throws IOException {
        List<ContractSettlementExcelVO> res = contractSettlementService.exportSettlementExcel(req);
        // 导出 Excel
        ExcelUtils.write(response, "退租清算单.xls", "数据", ContractSettlementExcelVO.class, res);
    }

    /**
     * 企业批量导出退租清算单
     */
    @GetMapping("/export-company-batch-settlement")
    @Operation(summary = "企业批量导出退租清算单")
//    @PreAuthorize("@ss.hasPermission('contract:export')")
    @OperateLog(type = EXPORT)
    public void exportSettlementCompanyBatchExcel(ContractSettlementReqExcelVO req, HttpServletResponse response) throws IOException {
        List<ContractSettlementExcelVO> res = contractSettlementService.exportSettlemenCompanyBatchtExcel(req);
        // 导出 Excel
        ExcelUtils.write(response, "退租清算单.xls", "数据", ContractSettlementExcelVO.class, res);
    }

    /**
     * 获取企业合同退租清单列表
     *
     * @param reqVO
     * @return
     */
    @PostMapping("/get-list-company")
    @Operation(summary = "通过合同id获取企业合同退租清单列表")
    public CommonResult<PageResult<ContractSettlementCompanyListRespVO>> getSettlementCompanyList(@RequestBody ContractSettlementGetListReqVO reqVO) {
        PageResult<ContractSettlementCompanyListRespVO> list = contractSettlementService.getSettlementCompanyList(reqVO);
        return success(list);
    }

    /**
     * 通过id查看企业退租清单
     *
     * @param id
     * @return
     */
    @GetMapping("/get-company")
    @Operation(summary = "通过id查看企业退租清单")
    public CommonResult<ContractSettlementCompanyListReqVO> getSettlementCompany(@RequestParam("id") Long id) {
        ContractSettlementCompanyListReqVO reqVO = contractSettlementService.getSettlementCompany(id);
        return success(reqVO);
    }

    /**
     * 通过id编辑企业退租清单编辑
     *
     * @param id
     * @return
     */
    @GetMapping("/update-company")
    @Operation(summary = "通过id编辑企业退租清单编辑")
    public CommonResult<CompanyContractRefundReqVO> getSettlementCompanyCompile(@RequestParam("id") Long id) {
        CompanyContractRefundReqVO reqVO = contractSettlementService.getSettlementCompanyCompile(id);
        return success(reqVO);
    }

    /**
     * 个人清算
     *
     * @return
     */
    @PostMapping("/person")
    @Operation(summary = "个人清算确认")
    public CommonResult<Void> settlement(@Valid @RequestBody SettlementReqVO reqVO) {
        contractSettlementService.settlementConfirm(reqVO);
        return success();
    }

    /**
     * 批量 个人清算
     */
    @PostMapping("/batch-settlement")
    @Operation(summary = "批量个人清算确认")
    public CommonResult<Void> batchSettlement(@Valid @RequestBody SettlementReqListVO reqVO) {
        contractSettlementService.settlementConfirmList(reqVO.getIds());
        return success();
    }

    /**
     * 企业批量单个清算
     *
     * @return
     */
    @PostMapping("/company-batch")
    @Operation(summary = "企业批量单个清算")
    public CommonResult<Void> settlementCompanyBatchConfirm(@Valid @RequestBody SettlementReqVO reqVO) {
        contractSettlementService.settlementCompanyBatchConfirm(reqVO);
        return success();
    }

    /**
     * 批量企业清算
     */
    @PostMapping("/batch-company-settlement")
    @Operation(summary = "批量企业清算")
    public CommonResult<Void> settlementCompanyBatchConfirmList(@Valid @RequestBody SettlementReqListVO reqVO) {
        contractSettlementService.settlementCompanyBatchConfirmList(reqVO.getIds());
        return success();
    }

    /**
     * 流入清算
     *
     * @param reqVO
     * @return
     */
    @PostMapping("/inflow/liquidation")
    public CommonResult<Long> inflowLiquidation(@RequestBody PayOrderCreateReqDTO reqVO) {
        Long id = contractSettlementService.inflowLiquidation(reqVO);
        return success(id);
    }

    /**
     * 企业合同清算
     *
     * @return
     */
    @PostMapping("/company")
    @Operation(summary = "企业清算确认")
    public CommonResult<Void> companySettlement(@Valid @RequestBody SettlementReqVO reqVO) {
        contractSettlementService.companySettlementConfirm(reqVO);
        return success();
    }

    @GetMapping("/pdf")
    public void pdf(@RequestParam("ids") String ids, HttpServletResponse response) throws Exception {
        List<SettlementExtDO> list = contractSettlementService.getSettlementPdfList(Arrays.asList(ids.split(",")));
        Font header = PdfUtils.getFont();
        header.setSize(18);
        header.setStyle(Font.FontStyle.BOLD.getValue());
        Font bold = PdfUtils.getFont();
        bold.setStyle(Font.FontStyle.BOLD.getValue());

        PdfUtils.PdfDoc doc = PdfUtils.newPdfDoc();
        OutputStream os = response.getOutputStream();
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(String.format("退租报告_%s.pdf", DateUtil.format(new Date(), "yyyyMMddHHmmss")), "UTF-8"));
        response.setContentType("application/pdf;charset=UTF-8");

        PdfWriter.getInstance(doc.getDoc(), os);
        doc.open();
        if (CollectionUtils.isEmpty(list)) {
            doc.addParagraph("未找到结算信息");
            doc.close();
            os.close();
            return;
        }

        for (SettlementExtDO vo : list) {
            List<SettlementDetailDO> detail = contractSettlementService.getSettlementDetail(vo.getId());
            doc.addParagraph(DateUtil.format(new Date(), "yyyy/MM/dd"));
            doc.addTable(4, tb -> {
                // 主表单信息
                tb.addCell("退租报告", 4, header, cell -> {
                            cell.setPaddingTop(5);
                            cell.setPaddingBottom(10);
                        })
                        .addCell("业务信息", 4, bold, Element.ALIGN_LEFT)
                        .addCell("退租编号").addCell(vo.getSettlementNo(), 3)
                        .addCell("退租日期", vo.getEndTime().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")), "退租类型",
                                vo.getEvictionReason())
                        .addCell("业务门店", vo.getApartmentName(), "业务管家", vo.getSignerName())
                        .addCell("房屋位置").addCell(vo.getRoomName(), 3)
                        .addCell("租户名称", vo.getCustomerName(), "租户电话", vo.getCustomerPhone())
                        .addCell("收款账户类型", (ContractSettlementTypeEnum.DEFAULT.getValue().equals(vo.getSettlementType())
                                ? "个人" : "企业"), "收款账户名称", vo.getCustomerName())
                        .addCell("收款行行号", vo.getBankCode(), "收款银行账号", vo.getCustomerCreditCard())
                        .addCell("收款账户银行").addCell(vo.getCustomerBankArea(), 3)
                        .addCell("合同租期").addCell(vo.getStartTime().toString() + "至" + vo.getEndTime().toString(), 3)
                        .addCell("附件").addCell(String.format("1、合同编号：%s；2、房屋交接确认单", vo.getContractNo()), 3);
                // 账单信息
                tb.addCell("账单信息", 4, bold, Element.ALIGN_LEFT)
                        .addCell("费用名称", "费用金额", "费用备注", "创建时间");
                if (CollectionUtils.isNotEmpty(detail)) {
                            for (SettlementDetailDO d : detail) {
                                tb.addCell(d.getFeeName(), d.getRefundableAmount().toString(), "",
                                        DateUtil.format(d.getCreateTime(), "yyyy/MM/dd HH:mm:ss"));
                            }
                        }
                        tb.addCell("总计").addCell(vo.getAmount().toString() + "元", 3);
                        // 流程处理信息
                        tb.addCell("处理信息记录", 4, bold, Element.ALIGN_LEFT);
                        if (StringUtils.isNotBlank(vo.getProcessInstanceId())) {
                            List<BpmTaskRespDTO> tasklist = bpmProcessInstanceApi.getAllTaskListByProcessInstanceId(vo.getProcessInstanceId());
                            PdfUtils.Table nestedTable = new PdfUtils.Table(5).addCell("处理人", "处理步骤", "审核意见", "处理结果", "处理时间");
                            if (CollectionUtils.isNotEmpty(tasklist)) {
                                for (BpmTaskRespDTO bpmTaskRespDTO : tasklist) {
                                    String handler = bpmTaskRespDTO.getAssigneeUsers().stream().findFirst().map(BpmTaskRespDTO.User::getNickname).orElse("");
                                    nestedTable.addCell(handler, bpmTaskRespDTO.getName(), bpmTaskRespDTO.getReason(), BpmProcessInstanceResultEnum.getResult(bpmTaskRespDTO.getResult()),
                                            bpmTaskRespDTO.getEndTime() != null ? DateUtil.format(bpmTaskRespDTO.getEndTime(), "yyyy/MM/dd HH:mm:ss") : "");
                                }
                            }
                            nestedTable.options(t -> {
                                t.setWidthPercentage(100);
                                try {
                                    t.setWidths(new float[]{18f, 32f, 18f, 12f, 20f});
                                } catch (DocumentException ignore) {
                                }
                            });
                            tb.addCell(nestedTable);

                        }
                        //备注打印
                        tb.addCell(String.format("备注 : %s", StrUtil.isNotBlank(vo.getRemark()) ? vo.getRemark() : "")
                                , 4, Element.ALIGN_LEFT);
                        tb.options(t -> {
                            t.setWidthPercentage(100);
                            try {
                                t.setWidths(new float[]{18f, 32f, 18f, 32f});
                            } catch (DocumentException ignore) {
                            }
                        });
                    }
            );
            doc.getDoc().newPage();
        }
        doc.close();
        os.close();
    }

    @GetMapping("/company-pdf")
    public void companypdf(@RequestParam("ids") String ids, HttpServletResponse response) throws Exception {
        List<SettlementExtDO> list = contractSettlementService.getSettlementCompanyPdfList(Arrays.asList(ids.split(","
        )));
        Font header = PdfUtils.getFont();
        header.setSize(18);
        header.setStyle(Font.FontStyle.BOLD.getValue());
        Font bold = PdfUtils.getFont();
        bold.setStyle(Font.FontStyle.BOLD.getValue());

        PdfUtils.PdfDoc doc = PdfUtils.newPdfDoc();
        OutputStream os = response.getOutputStream();
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(String.format("退租报告_%s" +
                ".pdf", DateUtil.format(new Date(), "yyyyMMddHHmmss")), "UTF-8"));
        response.setContentType("application/pdf;charset=UTF-8");

        PdfWriter.getInstance(doc.getDoc(), os);
        doc.open();
        if (CollectionUtils.isEmpty(list)) {
            doc.addParagraph("未找到结算信息");
            doc.close();
            os.close();
            return;
        }

        for (SettlementExtDO vo : list) {
            List<SettlementDetailDO> detail = contractSettlementService.getSettlementDetail(vo.getId());
            doc.addParagraph(DateUtil.format(new Date(), "yyyy/MM/dd"));
            doc.addTable(4, tb -> {
                        // 主表单信息
                        tb.addCell("退租报告", 4, header, cell -> {
                                    cell.setPaddingTop(5);
                                    cell.setPaddingBottom(10);
                                })
                                .addCell("业务信息", 4, bold, Element.ALIGN_LEFT)
                                .addCell("退租编号").addCell(vo.getSettlementNo(), 3)
                                .addCell("退租日期", vo.getEndTime().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")),
                                        "退租类型",
                                        vo.getEvictionReason())
                                .addCell("业务门店", vo.getApartmentName(), "业务管家", vo.getSignerName());
                        if (ContractSettlementTypeEnum.COMPANY_BATCH.getValue().equals(vo.getSettlementType())) {
                            tb.addCell("房屋位置").addCell(vo.getRoomName().replaceAll(",", "\n"), 3);
                        } else {
                            tb.addCell("房屋位置").addCell(vo.getRoomName(), 3);
                        }
                        tb.addCell("租户名称", vo.getCustomerName(), "租户电话", vo.getCustomerPhone())
                                .addCell("收款账户类型",
                                        (ContractSettlementTypeEnum.DEFAULT.getValue().equals(vo.getSettlementType())
                                        ? "个人" : "企业"), "收款账户名称", vo.getCustomerName())
                                .addCell("收款行行号", vo.getBankCode(), "收款银行账号", vo.getCustomerCreditCard())
                                .addCell("收款账户银行").addCell(vo.getCustomerBankArea(), 3)
                                .addCell("合同租期").addCell(vo.getStartTime().toString() + "至" + vo.getEndTime().toString(), 3)
                                .addCell("附件").addCell(String.format("1、合同编号：%s；2、房屋交接确认单", vo.getContractNo()), 3);
                        // 账单信息
                        tb.addCell("账单信息", 4, bold, Element.ALIGN_LEFT)
                                .addCell("费用名称", "费用金额", "费用备注", "创建时间");
                        if (CollectionUtils.isNotEmpty(detail)) {
                            for (SettlementDetailDO d : detail) {
                                tb.addCell(d.getFeeName(), d.getRefundableAmount().toString(), "",
                                        DateUtil.format(d.getCreateTime(), "yyyy/MM/dd HH:mm:ss"));
                            }
                        }
                        tb.addCell("总计").addCell(vo.getAmount().toString() + "元", 3);
                        // 流程处理信息
                        tb.addCell("处理信息记录", 4, bold, Element.ALIGN_LEFT);
                        if (StringUtils.isNotBlank(vo.getProcessInstanceId())) {
                            List<BpmTaskRespDTO> tasklist =
                                    bpmProcessInstanceApi.getAllTaskListByProcessInstanceId(vo.getProcessInstanceId());
                            PdfUtils.Table nestedTable = new PdfUtils.Table(5).addCell("处理人", "处理步骤", "审核意见", "处理结果",
                                    "处理时间");
                            if (CollectionUtils.isNotEmpty(tasklist)) {
                                for (BpmTaskRespDTO bpmTaskRespDTO : tasklist) {
                                    String handler =
                                            bpmTaskRespDTO.getAssigneeUsers().stream().findFirst().map(BpmTaskRespDTO.User::getNickname).orElse("");
                                    nestedTable.addCell(handler, bpmTaskRespDTO.getName(), bpmTaskRespDTO.getReason()
                                            , BpmProcessInstanceResultEnum.getResult(bpmTaskRespDTO.getResult()),
                                            bpmTaskRespDTO.getEndTime() != null ?
                                                    DateUtil.format(bpmTaskRespDTO.getEndTime(), "yyyy/MM/dd " +
                                                            "HH:mm:ss") : "");
                                }
                            }
                            nestedTable.options(t -> {
                                t.setWidthPercentage(100);
                                try {
                                    t.setWidths(new float[]{18f, 32f, 18f, 12f, 20f});
                                } catch (DocumentException ignore) {
                                }
                            });
                            tb.addCell(nestedTable);

                        }
                        //备注打印
                        tb.addCell(String.format("备注 : %s", StrUtil.isNotBlank(vo.getRemark()) ? vo.getRemark() : "")
                                , 4, Element.ALIGN_LEFT);
                        tb.options(t -> {
                            t.setWidthPercentage(100);
                            try {
                                t.setWidths(new float[]{18f, 32f, 18f, 32f});
                            } catch (DocumentException ignore) {
                            }
                        });
                    }
            );
            doc.getDoc().newPage();
        }
        doc.close();
        os.close();
    }

    /**
     * 退租清算管家端待办清算角标
     */
    @PostMapping("/count-num")
    @Operation(summary = "退租清算管家端待办清算角标")
    public CommonResult<Long> getSettlementCount() {
        return success(contractSettlementService.getSettlementCount());
    }

    /**
     * 查询 审批明细
     */
    @GetMapping("/get-settlement-detail-count")
    @Operation(summary = "查询 审批明细")
    public CommonResult<RentOrderCountVO> getSettlementDetailCount(@Valid @RequestParam("id") Long id) {
        RentOrderCountVO settlementDetailCount = contractSettlementService.getSettlementDetailCount(id);
        return success(settlementDetailCount);
    }
    /**
     * 通过审批流程id获取租客合同退租清单列表
     *
     * @param id
     * @return
     */
    @GetMapping("/get-process-instance-id")
    @Operation(summary = "通过审批流程id获取租客合同退租清单列表")
    public CommonResult<ContractSettlementListReqVO> getSettlementByProcessInstanceId(@RequestParam("id") String id) {
        ContractSettlementListReqVO reqVO = contractSettlementService.getSettlementByProcessInstanceId(id);
        return success(reqVO);
    }
}
